<template>
  <div class="content-box">
    <component :is="'el-form'" v-bind="props.options.form" ref="proFormRef" :model="model">
      <template v-for="(item, index) in props.options.columns" :key="index">
        <component :is="'el-form-item'" v-bind="item.formItem" trigger="blur" :show-message="false">
          <!-- 详情 -->
          <div v-if="type === 'show'" class="show_info">
            <!-- 图片详情 -->
            <template v-if="item.attrs.typeName == 'CyUploadImage' || item.attrs.typeName == 'cy-upload-image'">
              <CyUploadImage :formType="type" v-bind="item.attrs" v-model="model[item.formItem.prop]"></CyUploadImage>
            </template>
            <!-- 文件列表 -->
            <template v-else-if="item.attrs.typeName == 'CyUploadImage' || item.attrs.typeName == 'cy-upload-file'
              ">
              <CyUploadFile :formType="type" v-bind="item.attrs" v-model="model[item.formItem.prop]"></CyUploadFile>
            </template>
            <!-- 其他：文本展示 -->
            <template v-else>
              <span>{{ model[item.formItem.prop] }}</span>
              <span v-if="item.inputSlot" class="show_info_append">{{
                item.inputSlot.content
              }}</span>
            </template>
          </div>
          <!--编辑 -->
          <template v-else>
            <!-- 自定义组件 -->
            <template v-if="item.formItem.customComponent">
              <component :is="item.attrs.typeName" :formType="type" v-bind="item.attrs"
                v-on="item.event ? item.event : {}" v-model="model[item.formItem.prop]" style="width: 100%">
              </component>
            </template>
            <!-- elemment组件和预制组件 -->
            <component v-else :is="`${item.attrs?.typeName}`" :formType="type" v-bind="item.attrs"
              v-on="item.event ? item.event : {}" v-model="model[item.formItem.prop]" style="width: 100%">
            </component>
          </template>
        </component>
      </template>
    </component>
  </div>
</template>

<script setup name="ProForm">
import { ref, watch, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
let model = ref({})
const emit = defineEmits(['valueChange'])
const proFormRef = ref(null)

watch(model.value,
  () => {
    if (model.value) emit('valueChange', model)
  },
  { deep: true }
)

// 验证
const validateForm = () => {
  return new Promise((resolve, reject) => {
    proFormRef.value.validate((valid, fields) => {
      if (valid) {
        resolve(model.value)
      } else {
        let tag = false
        for (let key in fields) {
          fields[key].forEach((item) => {
            if (item) {
              if (!item.fieldValue) tag = true
              else ElMessage.error({ message: item.message })
            }
          })
        }
        if (tag) ElMessage.error({ message: '缺少必填项' })
        reject()
      }
    })
  })
}

// 设置form值  obj:object
const setValue = (obj) => {
  if (obj && obj instanceof Object) {
    for (let key in obj) {
      // if (props.options.columns.findIndex(item => item.formItem.prop == key) >= 0)
        model.value[key] = obj[key]
      // else delete model.value[key]
    }
  }
}
const getValue = () => {
  let value = {}
  Object.keys(model.value).forEach(keys => {
    if (props.options.columns.findIndex(item => item.formItem.prop == keys) >= 0)
      value[keys] = model.value[keys]
  })
  return JSON.parse(JSON.stringify(value))
}
const clear = () => {
  Object.keys(model.value).forEach(key => {
    if (isInstanceOf(model.value[key], String)) {
      model.value[key] = ''
    } else if ('isArray', Array.isArray(model.value[key])) {
      model.value[key] = []
    }
    else if (isInstanceOf(model.value[key], Object)) {
      model.value[key] = {}
    }
    else {
      model.value[key] = null
    }
  })
}
const isInstanceOf = (obj, ctor) => {
  var proto = Object.getPrototypeOf(obj)
  while (proto != null) {
    if (proto === ctor.prototype) {
      return true
    }
    proto = Object.getPrototypeOf(proto)
  }
  return false
}

onMounted(() => { })
defineExpose({ model,validateForm, getValue, setValue, clear })
const props = defineProps({
  type: String, // 表格类型 show:不可编辑
  options: {
    // 表单整体配置项
    type: Object,
    default() {
      return {
        form: {
          inline: false,
          labelPosition: 'right',
          labelWidth: '80px',
          size: 'large',
          disabled: false,
          labelSuffix: ' :',
        },
        columns: [
          {
            formItem: {
              label: '用户名',
              prop: 'username',
              labelWidth: '180px',
              required: true,
              value: '陈莹',
            },
            attrs: {
              typeName: 'input',
              clearable: true,
              placeholder: '请输入用户名',
              disabled: true,
            },
          },
          {
            formItem: {
              label: '密码',
              prop: 'password',
              class: 'data',
              style: 'width:200px',
            },
            attrs: {
              typeName: 'input',
              clearable: true,
              autofocus: true,
              placeholder: '请输入密码',
              type: 'password',
            },
          },
          {
            formItem: {
              label: '邮箱',
              prop: 'email',
              rules: {
                required: false,
                validator: (rule, value, callback) => {
                  if (!value) {
                    callback()
                    return
                  }
                  let tag = /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/.test(value)
                  if (tag) callback()
                  else callback(new Error('请输入正确的Email'))
                },
                trigger: 'blur',
              },
            },
            attrs: {
              typeName: 'input',
              placeholder: '请输入邮箱',
              clearable: true,
            },
          },
        ],
      }
    },
  },
})
</script>
<script>
import CyRadioGroup from './components/radioGroup.vue'
import CyUploadFile from './components/upLoadfile.vue'
import CyUploadImage from './components/upLoadImage.vue'
import CyTransfer from './components/transfer.vue'
import CySelectMonths from '../selectMonths/index.vue'
import CySelect from '../select/index.vue'
export default {
  components: { CyRadioGroup, CyUploadFile, CyUploadImage, CyTransfer ,CySelect,CySelectMonths},
  name: 'ProForm',
}
</script>

<style scoped lang="scss">
@import './index.scss';
</style>
